#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <algorithm>
#include <initializer_list>
#include <vector>
#include <string>
#include <stack>
#include <list>
#include <map>
#include <functional>

using namespace std;

struct Point
{
	int _x;
	int _y;
};

// 在C++98中，标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定

// C++11扩大了用大括号括起的列表(初始化列表)的使用范围
// 使其可用于所有的内置类型和用户自定义的类型
// 使用初始化列表时，可添加等号(=)，也可不添加(很猥琐，个人不喜欢)

struct Date
{
	int _year;
	int _month;
	int _day;

	Date(int year, int month, int day)
		:_year(year)
		,_month(month)
		,_day(day)
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
};

//// 一切皆可用列表初始化
//// 并且可以省略 (=) 符号
//int main()
//{
//	int array1[] = { 1, 2, 3, 4, 5 };
//	int array2[] = { 0 };
//	
//	Point p = { 1, 2 };
//
//	Date d1 = { 2025, 1, 8 };
//	const Date& d2 = { 2025, 1, 8 };
//
//	return 0;
//}

//int main()
//{
//	// {} 必须与Date构造参数匹配
//	Date d1 = { 2025, 1, 8 };
//
//	// {} 列表中可以有任意多个值
//	// 是先把这几个值转换成 initializer_list
//	vector<int> v1 = { 1, 2, 3, 4, 5 };
//
//	std::initializer_list<int> mylist;
//	mylist = { 10, 20, 30 };
//	cout << sizeof(mylist) << endl;
//
//	cout << mylist.begin() << endl;
//	cout << mylist.end() << endl;
//	cout << &d1 << endl;
//	
//	int a[] = { 10, 20, 30 };
//	map<string, string> dict = { {"sort0", "排序"}, {"sort1", "排序"}, {"sort2", "排序"} };
//
//	return 0;
//}

//// 让模拟实现的vector也支持{}初始化 和 赋值
//namespace HQ
//{
//	template<class T>
//	class vector {
//	public:
//		typedef T* iterator;
//		vector(initializer_list<T> l)
//		{
//			_start = new T[l.size()];
//			_finish = _start + l.size();
//			_endofstorage = _start + l.size();
//			iterator vit = _start;
//			typename initializer_list<T>::iterator lit = l.begin();
//			while (lit != l.end())
//			{
//				*vit++ = *lit++;
//			}
//			//for (auto e : l)
//			//   *vit++ = e;
//		}
//		vector<T>& operator=(initializer_list<T> l) {
//			vector<T> tmp(l);
//			std::swap(_start, tmp._start);
//			std::swap(_finish, tmp._finish);
//			std::swap(_endofstorage, tmp._endofstorage);
//			return *this;
//		}
//	private:
//		iterator _start;
//		iterator _finish;
//		iterator _endofstorage;
//	};
//}

//// auto推导类型
//int main()
//{
//	int i = 10;
//	auto p = &i;
//	auto pf = strcpy;
//
//	cout << typeid(p).name() << endl;
//	cout << typeid(pf).name() << endl;
//
//	map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
//	//map<string, string>::iterator it = dict.begin();
//
//	auto it = dict.begin();
//
//	return 0;
//}

// decltype
// 将变量的类型声明为表达式指定的类型
// decltype的一些使用使用场景
// 
//template<class T1, class T2>
//void F(T1 t1, T2 t2)
//{
//	decltype(t1 * t2) ret;
//	cout << typeid(ret).name() << endl;
//}
//
//int main()
//{
//	const int x = 1;
//	double y = 2.2;
//
//	decltype(x * y) ret; // ret的类型是double
//	decltype(&x) p;		 // p的类型是int*
//
//	cout << typeid(ret).name() << endl;
//	cout << typeid(p).name() << endl;
//	F(1, 'a');
//
//	return 0;
//}

//// nullptr
//// 由于C++中NULL被定义成字面量0，这样就可能会带来一些问题
//// 因为0既能指针常量，又能表示整形常量。
//// 所以出于清晰和安全的角度考虑
//// C++11中新增了nullptr，用于表示空指针
//
//void func(int x)
//{
//	cout << "void func(int x)" << endl;
//}
//
//void func(int* p)
//{
//	cout << "void func(int* p)" << endl;
//}
//
//int main()
//{
//	func(NULL);
//
//	// C中void指针可以隐式类型转换成任意类型的指针
//	// Cpp不行
//	//func(((void*)0));
//
//	//func(nullptr);
//
//	return 0;
//}

// 范围for
// 底层就是迭代器

// 新的容器
// 以下是常用的两个
// unordered_map & unordered_set

// 左值右值引用

// 以下的p、b、c、*p都是左值
// 右值引用是 C++11 之后新出的特性

// 左值是一个表示数据的表达式，标志是可以获取它的地址
// 右值也是一个表示数据的表达式，如：字面常量、表达式返回值、函数返回值

//#include <iostream>
//using namespace std;
//
//int main()
//{
//	// 以下的p、b、c、*p都是左值
//	int* p = new int(0);
//	int b = 1;
//	const int c = b;
//	*p = 10;
//	string s("11111");
//
//	// 右值：不能取地址
//	// 常见有常量临时对象，匿名对象
//	double x = 1.1, y = 2.2;
//	x + y;
//	fmin(x, y);
//
//	// 以下几个都是对右值的右值引用
//	int&& rr1 = 10;
//	double&& rr2 = x + y;
//	double&& rr3 = fmin(x, y);
//
//	return 0;
//}

//int main()
//{
//	int x = 1, y = 2;
//
//	// 左值引用给右值取别名，不能直接引用，但是 const 左值引用可以
//	const int& rx1 = 10;
//	const int& rx2 = x + y;
//	const double& rx3 = fmin(x, y);
//	const string& rx4 = string("1111");
//
//	// void push(const T& x);
//	vector<string> v;
//	string s("1111");
//
//	string s1 = "1111";
//	v.push_back(s1);
//	v.push_back(string("11111"));
//	v.push_back("111111");
//
//	// 右值引用给左值取别名：不能引用，但是 move(左值) 以后右值引用可以引用
//	// int&& rrx = x;
//	int&& rrx = move(x);
//
//	return 0;
//}

//int main()
//{
//	// 底层的实现与上层可能是有区别的
//	// 在没有完全实现上层的时候，不要先去看下层
//	int x = 0;
//	int& r1 = x;
//	int&& rr1 = x + 10;
//	int* p = &x;
//
//
//	return 0;
//}

// 引用的意义：减少拷贝
// 左值引用有些问题无法解决，这下才有右值传参
// 左值引用没有彻底解决的场景：传返回值

// 在bit::string to_string(int value)函数中可以看到
// 这里只能使用传值返回，传值返回会导致至少1次拷贝构造
// (如果是一些旧一点的编译器可能是两次拷贝构造)。

// 移动构造
// 临时创建的对象，不能取地址，用完就要消亡


//void* GetMemory(size_t size)
//{
//	return malloc(size);
//}
//int main()
//{
//	//如果没有带参数，推导函数的类型
//	cout << typeid(decltype(GetMemory)).name() << endl;
//	//如果带参数列表，推导的是函数返回值的类型，注意：此处只是推演，不会执行函数
//	cout << typeid(decltype(GetMemory(0))).name() << endl;
//	return 0;
//}

//// 后续使用中都退化成了左值
//void Fun(int& x) { cout << "左值引用" << endl; }
//void Fun(const int& x) { cout << "const 左值引用" << endl; }
//
//void Fun(int&& x) { cout << "右值引用" << endl; }
//void Fun(const int&& x) { cout << "const 右值引用" << endl; }
//
//template<typename T>
//// 在函数模板中，下面的 && 表示万能引用
//void PerfectForward(T&& t)
//{
//	// 模板实例化是左值引用，保持属性直接传参给Fun
//	// 模板实例化是右值引用，右值引用属性会退化成左值
//	Fun(t);
//}
//
//int main()
//{
//	PerfectForward(10);
//	int a = 5;
//
//	PerfectForward(a);
//	PerfectForward(std::move(a)); 
//	 
//	const int b = 8;
//	PerfectForward(b);
//	PerfectForward(std::move(b));
//
//	return 0;
//}

//// 完美转发
//// std::forward<T>(t)在传参的过程中保持了t的原生类型属性。
//void Fun(int& x) { cout << "左值引用" << endl; }
//void Fun(const int& x) { cout << "const 左值引用" << endl; }
//
//void Fun(int&& x) { cout << "右值引用" << endl; }
//void Fun(const int&& x) { cout << "const 右值引用" << endl; }
//
//template<typename T>
//void PerfectForward(T&& t)
//{
//	Fun(std::forward<T>(t));
//}
//
//int main()
//{
//	PerfectForward(10);				// 右值
//
//	int a = 0;
//	PerfectForward(a);				// 左值
//
//	const int b = 0;
//
//	PerfectForward(b);				// const 左值
//	PerfectForward(std::move(b));	// const 右值
//
//	return 0;
//}

//C++11允许在类定义时给成员变量初始缺省值，默认生成构造函数会使用这些缺省值初始化

//如果能想要限制某些默认函数的生成，在C++98中，是该函数设置成private，并且只声明补丁
//已，这样只要其他人想要调用就会报错。在C++11中更简单，只需在该函数声明加上 = delete即
//可，该语法指示编译器不生成对应函数的默认版本，称 = delete修饰的函数为删除函数。

//void Print()
//{
//	cout << endl;
//}
//
//template <class T, class ...Args>
//void Print(T&& x, Args&&...args)
//{
//	cout << x << " ";
//	Print(args...);
//}
//
// 编译时递归推导解析参数
//template <class ...Args>
//void showList(Args&&...args) 
//{
//	 可变参数模板编译时解析
//	cout << sizeof...(args) << endl;
//
//	 打印参数包内容
//	 下面是运行获取和解析，所以不支持这样用
//	Print(args...);
//}
//
// Args是一个模板参数包，args是一个函数形参参数包
// 声明一个参数包 Args...args ，这个参数包中可以包含 0 到 任意个 参数
//
//int main()
//{
//	showList();
//	showList(1);
//	showList(1, 2);
//	showList(1, "1111", 2.2);
//
//	return 0;
//}

//template <class T>
//int PrintArg(T&& t)
//{
//	cout << t << " ";
//	return 0;
//}
//
//template <class ...Args>
//void ShowList(Args&&... args)
//{
//	int arr[] = { PrintArgs(args)... };
//	cout << endl;
//}
//
//int main()
//{
//	ShowList(1);
//	ShowList(1, 'A');
//	ShowList(1, 'A', std::string("sort"));
//
//	return 0;
//}

//template <class ...Args>
//void ShowList(Args... args)
//{
//	int arr[] = { (cout << (args) << " ", 0)... };
//	cout << endl; 
//}
//
//int main()
//{ 
//	ShowList(1, 'A', std::string("111"));
//
//	return 0;
//}

//int main()
//{
//	list<string> lt;
//
//	// 左值
//	string s1("1111");
//	lt.emplace_back(s1);
//
//	// 右值
//	lt.emplace_back(move(s1));
//	pair<string, int> kv("苹果", 1);
//
//	list<pair<string, int>> lt1;
//	lt1.emplace_back("苹果", 1);
//
//	return 0;
//}

//// lambda表达式
//// C++98中
//// 如果每次比较的逻辑不一样，还要去实现多个类
//struct Goods
//{
//	string _name;	// 名字
//	double _price;  // 价格
//	int _evaluate;  // 评价
//	// ... 
//
//	Goods(const char* str, double price, int evaluate)
//		:_name(str)
//		,_price(price)
//		,_evaluate(evaluate)
//	{}
//};
//
//struct ComparePriceLess
//{
//	bool operator()(const Goods& gl, const Goods& gr)
//	{
//		return gl._price < gr._price;
//	}
//};
//
//struct ComparePriceGreater
//{
//	bool operator()(const Goods& gl, const Goods& gr)
//	{
//		return gl._price > gr._price;
//	}
//};
//
//int main()
//{
//	vector<Goods> v = { {"苹果", 2.1, 5}, {"香蕉", 3, 4}, {"橙子", 2.2, 3}, { "菠萝", 1.5, 4 } };
//
//	sort(v.begin(), v.end(), ComparePriceLess());
//	sort(v.begin(), v.end(), ComparePriceGreater());
//
//	return 0;
//}

// lambda表达式书写格式：[capture-list](parameters)mutable->return-type{statement}
// lambda的本质是一个匿名函数的对象
//[capture - list] : 捕捉列表，该列表总是出现在lambda函数的开始位置，编译器根据[]来
//判断接下来的代码是否为lambda函数，捕捉列表能够捕捉上下文中的变量供lambda
//函数使用。

//(parameters)：参数列表。与普通函数的参数列表一致，如果不需要参数传递，则可以
//连同()一起省略

//mutable：默认情况下，lambda函数总是一个const函数，mutable可以取消其常量
//性。使用该修饰符时，参数列表不可省略(即使参数为空)。
// }
//};

//->returntype：返回值类型。用追踪返回类型形式声明函数的返回值类型，没有返回
//值时此部分可省略。返回值类型明确情况下，也可省略，由编译器对返回类型进行推
//导。

//{ statement }：函数体。在该函数体内，除了可以使用其参数外，还可以使用所有捕获
//到的变量。

//int main()
//{
//	auto add1 = [](int x, int y)->int {return x + y;};
//	cout << add1(1, 2) << endl;
//
//	auto func1 = []()->int 
//	{
//		cout << "Hello, bit" << endl;
//		cout << "Hello, world!" << endl;
//
//		return 0;
//	};
//
//	func1();
//
//	return 0;
//}

////[var]：表示值传递方式捕捉变量var
////[=]：表示值传递方式捕获所有父作用域中的变量(包括this)
////[&var]：表示引用传递捕捉变量var
////[&]：表示引用传递捕捉所有父作用域中的变量(包括this)
////[this]：表示值传递方式捕捉当前的this指针
//
//// 捕捉列表在任何条件下都不可以省略
//int main()
//{
//	int a = 0, b = 1;
//
//	auto swap1 = [](int& x, int& y)
//		{
//			// 只能用当前lambda局部域和捕捉的对象和全局对象
//			int tmp = x;
//			x = y;
//			y = tmp;
//		};
//
//	swap1(a, b);
//
//	// 传值捕捉本质是一种拷贝，并且 const 修饰了
//	// mutable相当于去掉 const 属性，可以修改了
//	// 但是修改了不会影响外面被捕捉的值，因为是一种拷贝
//	auto swap2 = [a, b]() mutable
//		{
//			int tmp = a;
//			a = b;
//			b = tmp;
//		};
//
//	swap2();
//
//	auto swap3 = [&a, &b]()
//		{
//			int tmp = a;
//			a = b;
//			b = tmp;
//		};
//
//	swap3();
//
//	return 0;
//}

//int main()
//{
//	int a = 0, b = 1, c = 2, d = 3;
//
//	// 所有值传值捕捉，用 “=”
//	auto func1 = [=]
//		{
//			int ret = a + b + c + d;
//			return ret;
//		};
//
//	// 所有值引用捕捉，用 “&”
//	auto func2 = [&]
//		{
//			a++;
//			b++;
//			c++;
//			d++;
//
//			int ret = a + b + c + d;
//			return ret;
//		};
//
//	// 混合捕捉
//	// 所有值以引用方式捕捉，b用传值捕捉
//	auto func3 = [&, b]
//		{
//			a++;
//			// b++;
//			d++;
//			int ret = a + b + c + d;
//			return ret;
//		};
//
//	return 0;


